package bz.ziro.kanbe.logic;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.slim3.datastore.Datastore;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.apphosting.api.ApiProxy;

import bz.ziro.kanbe.bean.MailData;

import bz.ziro.kanbe.dao.PageDao;
import bz.ziro.kanbe.dao.TemplateDao;
import bz.ziro.kanbe.model.Mail;
import bz.ziro.kanbe.model.Page;
import bz.ziro.kanbe.model.SiteFile;
import bz.ziro.kanbe.model.Template;
import bz.ziro.kanbe.util.KeyFactory;

/**
 * メール作成ロジック
 * @author Administrator
 */
public class MailLogic {

    //@SuppressWarnings("unused")
    private static final Logger logger = Logger.getLogger(MailLogic.class.getName());
	/**
	 * メール内容とメールデータからページを作成する
	 * @param mail
	 * @param data
	 */
	public static void createPage(Mail mail, MailData data) {
		
		Page registPage = new Page();
		//サイトキーを取得
		Key siteKey = mail.getSiteKey();
        logger.info(String.valueOf(siteKey.getId()));
		registPage.setSiteKey(siteKey);
		//親ページを取得
		Key parentPageKey = mail.getParentPageKey();
		registPage.setParentPageKey(parentPageKey);
        logger.info(String.valueOf(parentPageKey.getId()));
		
		registPage.setName(data.getSubject());
		registPage.setDetail("");
	
		int cnt = PageDao.findParentCount(parentPageKey);
		//優先順位を１つ上に登録する
		registPage.setPriority(cnt + 1);

		Key siteTemplateKey = mail.getSiteTemplateKey();
		Key pageTemplateKey = mail.getPageTemplateKey();
        logger.info(String.valueOf(siteTemplateKey.getId()));
        logger.info(String.valueOf(pageTemplateKey.getId()));
		//サイトテンプレートキーを設定する
		registPage.setSiteTemplateKey(siteTemplateKey);
		//ページテンプレートキーを設定する
		registPage.setPageTemplateKey(pageTemplateKey);

        //作成者情報を取得
        UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();
        registPage.setCreateDate(new Date());
        registPage.setCreator(user);

        //ページのキーを取得
        Key key = KeyFactory.allocatePageKey(siteKey.getId());
        registPage.setKey(key);
        
        logger.info(String.valueOf(key.getId()));
      
        //テンプレートを検索
        Template template = TemplateDao.find(siteKey.getId(), pageTemplateKey.getId());
        String schema = template.getSchema();

        //XMLデータを設定
        registPage.setPageData(createXml(mail,data,schema));

		Datastore.put(registPage);
	}

	/**
	 * XMLデータの設定
	 * @param registPage
	 * @param mail
	 * @param data 
	 * @param schema
	 */
	private static String createXml(Mail mail, MailData data, String schema) {
	
		String xmlData = "<xmlData>";
        // ドキュメントビルダーファクトリを生成
        DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
        try {
            // ドキュメントビルダーを生成
            DocumentBuilder builder = dbfactory.newDocumentBuilder();
            // パースを実行してDocumentオブジェクトを取得
            Document doc = builder.parse(new ByteArrayInputStream(schema.getBytes("UTF-8")));

            Element root = doc.getDocumentElement();
            NodeList paramList = root.getElementsByTagName("parameter");
            
            String subjectName = mail.getSubjectName();
            String textName    = mail.getTextName();
            String fileName    = mail.getFileName();

            //属性数回繰り返す
            for ( int cnt = 0; cnt < paramList.getLength(); ++cnt ) {
                Element dataElm = (Element)paramList.item(cnt);

                //宣言名を取得
                String defineName = dataElm.getAttribute("define");
                //種別を取得
                String type = dataElm.getAttribute("type");
               
                //タグを追加
                xmlData += "<parameter name=\"" + defineName +  "\" type=\"" + type + "\"><![CDATA[";
                
                if ( subjectName.equals(defineName) ) {
                	xmlData += data.getSubject();
                } else if ( textName.equals(defineName) ) {
                	xmlData += data.getText();
                } else if ( fileName.equals(defineName) ) {
                	
                	//ファイルを作成する
                	byte[] fileData = data.getFileData();
                	if ( fileData != null ) {
                		
                		SiteFile file = new SiteFile();
                		Key key = KeyFactory.allocateFileKey();
                		file.setKey(key);
                		file.setName(data.getFileName());
                		file.setType(data.getFileType());
                		file.setFile(data.getFileData());
                		
                        UserService userService = UserServiceFactory.getUserService();
                        User user = userService.getCurrentUser();
                		file.setCreateDate(new Date());
                		file.setCreator(user);
                		//ファイルを登録
                		Datastore.put(file);
                		//IDを設定
                		xmlData += key.getId();
                	}
                }

                xmlData += "]]></parameter>";
                
            }
        } catch (Exception ex) {
        	logger.warning(ex.getMessage());
        }
		xmlData += "</xmlData>";
		return xmlData;
	}
	

	/**
	 * コメントメール
	 * @param path
	 */
	public static void sendCommentMail(String path) {
		String text = path + "にコメントがされました。";
		sendMail("コメントが投稿されました。",text);
	}
	/**
	 * コメントメール
	 * @param path
	 */
	public static void sendMail(String text) {
		sendMail("問い合わせが届きました。",text);
	}

	/**
	 * メール送信
	 * @param subject
	 * @param text
	 * @throws UnsupportedEncodingException 
	 */
	private static void sendMail(String subject,String text) {

		String email = ApiProxy.getCurrentEnvironment().getEmail();
		Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);
        try {
            Message msg = new MimeMessage(session);
            msg.setFrom(new InternetAddress(email));
            msg.addRecipient(Message.RecipientType.TO, new InternetAddress(email));
            msg.setSubject(MimeUtility.encodeText(subject,"iso-2022-jp","B"));
            msg.setText(text);
            Transport.send(msg);

        } catch (AddressException e) {
        	logger.info(e.getMessage());
        } catch (MessagingException e) {
        	logger.info(e.getMessage());
        } catch (UnsupportedEncodingException e) {
        	logger.info(e.getMessage());
		}
	}

	/**
	 * メールデータを作成する
	 * @param fromBuf
	 * @param toBuf
	 * @param mailList
	 * @return
	 */
	public static Mail findMailData(MailData mailData, List<Mail> mailList) {

		//送信候補を取得
		List<String> fromAddress = mailData.getFromAddress();
		//受信候補を取得
		List<String> toAddress   = mailData.getToAddress();
		
		//メール設定数回 回す
		for ( Mail mail : mailList ) {

			//それぞれのアドレスを取得
			String from = mail.getFromAddress();
			String to = mail.getToAddress();
	
			//FromとToを検索
			int fromIdx = -1;
			//カンマ区切りにする
			String[] fromArray = from.split(",");
			
			//アドレス分判定
			for ( String add : fromArray ) {
				//Fromで拾ってきた奴
				for ( String fromBuf : fromAddress ) {
					fromIdx = fromBuf.indexOf(add);
					//存在した場合終了
					if ( fromIdx >= 0 ) break;
				}
				if ( fromIdx >= 0 ) break;
			}

			int toIdx = -1;
			//Toで拾ってきた数回繰り返す
			for ( String toBuf : toAddress ) {
				toIdx = toBuf.indexOf(to);
				if ( toIdx >= 0 ) break;
			}

			//どっちとも存在した場合
			if ( fromIdx >= 0 && toIdx >= 0 ) {
				return mail;
			}
		}
		return null;
	}
}
